package hku.cs.eclunuo.handlers;

import hku.cs.eclunuo.LunuoLog;
import hku.cs.eclunuo.builders.SootBuilder;
import hku.cs.eclunuo.nature.SootNature;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

public class AddSootBuilder extends AbstractHandler implements IHandler {

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		Collection<IProject> projects = getSelectedProjects();

		for (IProject project : projects) {
			toggleBuilder(project);
		}
		
		return null;
	}

	
//	private void doRead(File f){
//		
//		if(f.isDirectory()){			
//			File fs[] = f.listFiles();
//			for(int i=0; i<fs.length; i++)				
//					doRead(fs[i]);
//			f.setWritable(false);
//		}else
//			f.setWritable(false);
//		
//	}
	
	private void toggleBuilder(final IProject project) {
		try {
			IProjectDescription description = project.getDescription();
			String[] natures = description.getNatureIds();

			for (int i = 0; i < natures.length; ++i) {
				if (SootNature.NATURE_ID.equals(natures[i])) {
					// Remove the nature
					String[] newNatures = new String[natures.length - 1];
					System.arraycopy(natures, 0, newNatures, 0, i);
					System.arraycopy(natures, i + 1, newNatures, i,
							natures.length - i - 1);
					description.setNatureIds(newNatures);
					project.setDescription(description, null);
					return;
				}
			}

			// Add the nature
			String[] newNatures = new String[natures.length + 1];
			System.arraycopy(natures, 0, newNatures, 0, natures.length);
			newNatures[natures.length] = SootNature.NATURE_ID;
			description.setNatureIds(newNatures);
			project.setDescription(description, null);
			
//			Display.getCurrent().asyncExec(new Runnable(){
//				@Override
//				public void run() {
//					try {
//						project.build(SootBuilder.FULL_BUILD,
//								SootBuilder.BUILDER_ID, null, null);
//					} catch (CoreException e) {
//						LunuoLog.logError(e);
//						e.printStackTrace();
//					}
//					
//				}
//				
//			});
			
			new Job("soot builder job") {
				protected IStatus run(IProgressMonitor monitor) {
					try {
						project.build(SootBuilder.FULL_BUILD,
								SootBuilder.BUILDER_ID, null, null);
					} catch (CoreException e) {
						LunuoLog.logError(e);
					}
					return Status.OK_STATUS;
				}
			}.schedule();
			
			
			
		} catch (CoreException e) {
		}
	}
	

	private Collection<IProject> getSelectedProjects() {
		Collection<IProject> projects = new HashSet<IProject>();

		IWorkbenchWindow window = PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow();
		ISelection selection = window.getActivePage().getSelection();
		if (selection instanceof IStructuredSelection) {
			for (Iterator<?> iter = ((IStructuredSelection) selection)
					.iterator(); iter.hasNext();) {
				Object elem = iter.next();
				if (!(elem instanceof IResource)) {
					if (!(elem instanceof IAdaptable))
						continue;
					elem = ((IAdaptable) elem).getAdapter(IResource.class);
					if (!(elem instanceof IResource))
						continue;
				}
				if (!(elem instanceof IProject)) {
					elem = ((IResource) elem).getProject();
					if (!(elem instanceof IProject))
						continue;
				}
				projects.add((IProject) elem);
			}
		}
		return projects;
	}

}
